package com.xintool.window.Buttons;

import com.xintool.mapper.PetMapper;
import com.xintool.mapper.PetsList;

import javax.swing.*;
import javax.swing.border.TitledBorder;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import java.awt.*;
import java.awt.event.ItemEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class Button_jljsq extends ButtonFactory {

    // 添加窗口实例跟踪
    private static JFrame calculatorFrame;

    //种族值的Map对象
    private PetMapper petMapper = new PetMapper();

    //种族值面板，用于刷新
    private JPanel raceValuePanel;
    //结果面板，用于刷新
    private JPanel resultPanel;
    //学习力面板，用于获取数据
    private JPanel effortValuePanel;
    //保存输入框引用以便获取值
    private List<JTextField> effortFields = new ArrayList<>();

    // 存储种族值标签引用
    private List<JLabel> raceValueLabels = new ArrayList<>();
    // 存储结果标签引用
    private List<JLabel> resultLabels  = new ArrayList<>();

    //等级
    private Integer level = 100;
    //个体
    private Integer individual = 31;


    @Override
    public JButton showButton() {
        // 利用按钮工厂创建按钮实例
        JButton button_jljsq = ButtonFactory.getButton("精灵计算");//按钮显示文本为“精灵计算”
        //添加点击事件监听
        button_jljsq.addActionListener(e -> createCalculatorWindow());

        return button_jljsq;
    }

    void createCalculatorWindow() {

        // 检查窗口是否已经存在
        if (calculatorFrame != null && calculatorFrame.isDisplayable()) {
            // 如果窗口存在则带到前台
            calculatorFrame.toFront();
            return;
        }
        calculatorFrame = new JFrame("精灵计算器");
        calculatorFrame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        calculatorFrame.addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosed(WindowEvent e) {
                // 窗口关闭时释放引用
                calculatorFrame = null;
            }
        });
        calculatorFrame.setSize(370, 430);
        calculatorFrame.setLocationRelativeTo(null);
        calculatorFrame.setResizable(false);         // 禁止调整窗口大小

        calculatorFrame.add(createMainPanel());
        // true表示窗口可见，false表示窗口不可见
        calculatorFrame.setVisible(true);
    }

    // 创建主面板的方法
    private JPanel createMainPanel() {
        // 创建一个新的JPanel对象，并使用BorderLayout布局管理器，水平和垂直间距均为10
        JPanel mainPanel = new JPanel(new BorderLayout(10, 10));
        // 设置面板的边框，创建一个空的边框，上下左右边距均为10
        mainPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));

        // 顶部搜索区域
        mainPanel.add(createSearchPanel(), BorderLayout.NORTH);

        // 中间主体区域
        mainPanel.add(createMainContent(), BorderLayout.CENTER);

        return mainPanel;
    }

    // 创建一个用于搜索的JPanel面板
    private JPanel createSearchPanel() {
        JPanel panel = new JPanel(new FlowLayout(FlowLayout.LEFT));
        panel.add(new JLabel("选择精灵："));
        JComboBox<String> petCombo = new JComboBox<>(PetsList.PETSLIST);
        petCombo.setMaximumRowCount(20);
        // 添加选择监听
        petCombo.addItemListener(e -> {
            if (e.getStateChange() == ItemEvent.SELECTED) {
                int selectedIndex = petCombo.getSelectedIndex();
                loadPetData(selectedIndex);
            }
        });

        panel.add(petCombo);
        return panel;
    }
    //自动获取并显示选中精灵数据
    private void loadPetData(int selectedIndex) {
        try {
            // 索引+1对应宠物ID
            int petId = selectedIndex + 1;
            List<Integer> raceValues = petMapper.getRaceValueById(petId);

            // 自动填充种族值
            for (int i = 0; i < raceValueLabels.size() && i < raceValues.size(); i++) {
                raceValueLabels.get(i).setText(String.valueOf(raceValues.get(i)));
            }
            reflashRaceValue(raceValues);
        } catch (Exception ex) {
            JOptionPane.showMessageDialog(null, "精灵数据加载异常 " + ex.getMessage());
        }
    }

    //刷新种族值面板
    private void reflashRaceValue(List<Integer> raceValueList) {
        for (int i = 0; i < raceValueLabels.size() && i < raceValueList.size(); i++) {
            raceValueLabels.get(i).setText(String.valueOf(raceValueList.get(i)));
        }
        // 强制刷新UI
        // 使用SwingUtilities.invokeLater方法来确保在事件调度线程（EDT）上执行后续的代码块
        // 这是因为Swing组件的更新必须在EDT上进行，以确保线程安全
        SwingUtilities.invokeLater(() -> {
            // 对raceValueLabels集合中的每个标签（Label）执行以下操作
            raceValueLabels.forEach(label -> {
                // 调用label的revalidate方法，该方法会重新验证此组件及其子组件的布局
                // 这通常在组件的内容或大小发生变化后调用，以确保布局是最新的
                label.revalidate();
                // 调用label的repaint方法，该方法会请求重新绘制此组件
                // 这通常在组件的外观需要更新时调用，以确保显示是最新的
                label.repaint();
            });
        });
    }

    // 创建一个JPanel，并设置其布局为GridLayout，1行2列，水平和垂直间距分别为15和0
    // 创建主内容组件的方法
    private JComponent createMainContent() {
        JPanel contentPanel = new JPanel(new GridLayout(1, 2, 15, 0));

        // 左侧配置区域
        contentPanel.add(createLeftPanel());

        // 右侧结果区域
        contentPanel.add(createRightPanel());

        return contentPanel;
    }

    // 创建配置面板的方法
    private JPanel createConfigPanel() {
        // 创建一个面板，使用GridLayout布局管理器，行数不限，列数为1，水平和垂直间距分别为0和10
        JPanel panel = new JPanel(new GridLayout(0, 1, 0, 5));
        // 设置面板的边框，标题为"基础配置"
        panel.setBorder(new TitledBorder("基础配置"));

        // 等级配置
        JPanel levelPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
        levelPanel.add(new JLabel("等级："));
        JTextField levelField = new JTextField(String.valueOf(level), 4);
        levelPanel.add(levelField);

        // 个体值
        JPanel ivPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
        ivPanel.add(new JLabel("个体："));
        JTextField ivCombo = new JTextField(String.valueOf(individual), 4);
        //滚动条
        //JComboBox<String> ivCombo = new JComboBox<>(new String[]{"31", "30", "29"});
        ivPanel.add(ivCombo);

        // 性格
        JPanel naturePanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
        naturePanel.add(new JLabel("性格："));
        JComboBox<String> natureCombo = new JComboBox<>(new String[]{"平衡",// 攻击型性格（提升攻击）
                "固执", "孤独", "调皮", "勇敢",

                // 特攻型性格（提升特攻）
                "保守", "稳重", "马虎", "冷静",

                // 速度型性格（提升速度）
                "开朗", "胆小", "急躁", "天真",

                // 防御型性格（提升防御）
                "大胆", "顽皮", "无虑", "悠闲",

                // 特防型性格（提升特防）
                "沉着", "温顺", "慎重", "狂妄",

                // 无修正性格
                 "害羞", "实干", "认真", "浮躁", "坦率"
        });
        natureCombo.setMaximumRowCount(21);
        naturePanel.add(natureCombo);

        // 按钮区域
        JPanel buttonPanel = new JPanel(new GridLayout(1, 2, 5, 0));
        JButton clearButton = new JButton("重置");
        clearButton.addActionListener(e -> reSet(levelField,ivCombo,natureCombo));
        JButton calcButton = new JButton("计算");
        calcButton.addActionListener(e ->calculateResult(levelField,ivCombo,natureCombo));
        buttonPanel.add(clearButton);
        buttonPanel.add(calcButton);

        // 组装配置面板
        panel.add(levelPanel);
        panel.add(ivPanel);
        panel.add(naturePanel);
        panel.add(buttonPanel);

        return panel;
    }

    //获取计算资源
    private void calculateResult(JTextField levelField,JTextField ivCombo,JComboBox<String> natureCombo){
        try {
            // 获取基础配置数据
            int level = Integer.parseInt(levelField.getText());
            int individual = Integer.parseInt(ivCombo.getText());
            String nature = (String) natureCombo.getSelectedItem();

            // 获取学习力数据
            List<Integer> effortValues = new ArrayList<>(6);
            for (JTextField tf : effortFields) {
                String input = tf.getText().trim();
                int value = 0;
                try {
                    value = input.isEmpty() ? 0 : Integer.parseInt(input);
                    value = Math.max(value, 0); // 负数自动归零
                    value = Math.min(value, 255); // 超上限自动修正
                } catch (NumberFormatException e) {
                    // 非数字输入自动视为0
                }
                effortValues.add(value);
            }

            // 获取种族值数据
            List<Integer> raceValues = new ArrayList<>();
            for (JLabel label : raceValueLabels) {
                int value = Integer.parseInt(label.getText());

                raceValues.add(value);
            }

            // 计算并更新结果
            calculateAndDisplay(level, individual, nature, effortValues, raceValues);
        } catch (NumberFormatException ex) {
            JOptionPane.showMessageDialog(null, "输入格式错误，请检查数字输入！");
        } catch (Exception ex) {
            JOptionPane.showMessageDialog(null, "计算错误: " + ex.getMessage());
        }
    }
    //计算结果
    private void calculateAndDisplay(int level, int individual, String nature,
                                     List<Integer> effortValues, List<Integer> raceValues) {
        // 验证数据完整性
        if (raceValues.size() != 6) throw new IllegalArgumentException("需要6项种族值");
        if (effortValues.size() != 6) throw new IllegalArgumentException("需要6项学习力");
        if (!PetsList.CHARACTER.containsKey(nature)) throw new IllegalArgumentException("未知性格类型");

        // 获取性格修正
        double[] modifiers = PetsList.CHARACTER.get(nature);

        // 计算结果集（体力、攻击、防御、特攻、特防、速度）
        List<Integer> resultValues = new ArrayList<>();

        // 体力计算（单独公式）
        int hp = (int) Math.floor(
                (raceValues.get(0) * 2 + effortValues.get(0)/4.0 + individual) * level / 100.0 + 10 + level
        );
        resultValues.add(hp);

        // 其他五项计算（攻击、防御、特攻、特防、速度）
        for (int i = 1; i <= 5; i++) {
            // 确定修正系数索引（攻击=0, 防御=1, 特攻=2, 特防=3, 速度=4）
            int modIndex = i - 1;
            double mod = modifiers[modIndex];

            // 学习力索引调整（体力不参与，所以effortValues从0开始是攻击）
            int effortIndex = (i == 5) ? 4 : i - 1; // 速度是effortValues最后一个

            //结果向下取整，学习力/4保留小数位运算
            int stat = (int) Math.floor(
                    ((raceValues.get(i) * 2 + effortValues.get(effortIndex+1)/4.0 + individual)
                            * level / 100.0 + 5)
                            * mod
            );
            resultValues.add(stat);
        }

        // 更新结果面板
        updateResultPanel(resultValues);
    }

    // 结果面板更新
    private void updateResultPanel(List<Integer> results) {
        // 获取结果面板组件
        for (int i = 0; i < resultLabels.size() && i < results.size(); i++) {
            resultLabels.get(i).setText(String.valueOf(results.get(i)));
        }

        // 强制刷新UI
        SwingUtilities.invokeLater(() -> {
            resultPanel.revalidate();
            resultPanel.repaint();

        });
    }

    //重置
    public void reSet(JTextField levelField,JTextField ivCombo,JComboBox<String> natureCombo){
        // 重置输入字段
        levelField.setText("100");
        ivCombo.setText("31");
        natureCombo.setSelectedIndex(0);

        // 清空学习力输入框
        SwingUtilities.invokeLater(() -> {
            for (JTextField tf : effortFields) {
                tf.setText("0"); // 将所有学习力输入框设为0
            }
        });

        // 清空结果
        updateResultPanel(Arrays.asList(0, 0, 0, 0, 0, 0));

        // 重置剩余学习力显示
        Component[] components = effortValuePanel.getComponents();
        if (components.length > 12) {
            ((JLabel)components[13]).setText("510");
        }
    }


    // 创建种族值面板
    private JPanel createRaceValuePanel() {
        // 创建一个新的JPanel对象，并设置其布局为GridLayout，参数(0, 2)表示无限行，每行2列
        raceValuePanel = new JPanel(new GridLayout(0, 2));
        // 设置面板的边框，使用TitledBorder，标题为"种族值"
        raceValuePanel.setBorder(new TitledBorder("种族值"));
        // 清空旧引用
        raceValueLabels.clear();

        // 定义一个字符串数组，包含精灵的六个属性：体力、攻击、防御、特攻、特防、速度
        String[] attributes = {"体力", "攻击", "防御", "特攻", "特防", "速度"};
        // 遍历属性数组
        for (String attr : attributes) {
            // 为每个属性创建一个JLabel，并添加到面板中
            raceValuePanel.add(new JLabel(attr));
            // 调用createValueLabel方法创建一个显示初始值为"0"的JLabel，并添加到面板中
            JLabel valueLabel = createValueLabel("0");
            raceValuePanel.add(valueLabel);
            raceValueLabels.add(valueLabel); // 保存到成员变量
        }
        // 返回创建好的面板
        return raceValuePanel;
    }

    // 创建左部份面板的方法
    private JPanel createLeftPanel() {
        // 创建一个新的JPanel对象，并使用BorderLayout布局管理器，水平和垂直间距分别为0和10
        JPanel panel = new JPanel(new BorderLayout(0, 10));

        // 基础配置区域
        panel.add(createConfigPanel(), BorderLayout.NORTH);

        // 种族值区域
        panel.add(createRaceValuePanel(), BorderLayout.SOUTH);

        return panel;
    }


    // 创建右部份面板的方法
    private JPanel createRightPanel() {
        // 创建一个新的JPanel对象，并使用BorderLayout布局管理器，水平和垂直间距分别为0和10
        JPanel panel = new JPanel(new BorderLayout(0, 10));

        // 计算结果区域
        panel.add(createCulculatePanel(), BorderLayout.SOUTH);

        // 学习力区域
        panel.add(createEffortValuePanel(), BorderLayout.NORTH);

        return panel;
    }

    // 创建计算结果面板
    private JPanel createCulculatePanel() {
        // 创建一个新的JPanel对象，并设置其布局为GridLayout，参数(0, 2)表示无限行，每行2列
        resultPanel = new JPanel(new GridLayout(0, 2));
        // 设置面板的边框，使用TitledBorder，标题为"计算结果"
        resultPanel.setBorder(new TitledBorder("计算结果"));
        resultLabels.clear();

        // 定义一个字符串数组，包含精灵的六个属性：体力、攻击、防御、特攻、特防、速度
        String[] attributes = {"体力", "攻击", "防御", "特攻", "特防", "速度"};
        // 遍历属性数组
        for (String attr : attributes) {
            resultPanel.add(new JLabel(attr));
            JLabel valueLabel = createValueLabel("0");
            resultPanel.add(valueLabel);
            resultLabels.add(valueLabel); // 保存结果标签
        }

        // 返回创建好的面板
        return  resultPanel;
    }

    // 创建学习力面板
    private JPanel createEffortValuePanel() {
        // 定义一个字符串数组，包含精灵的六种属性：体力、攻击、防御、特攻、特防、速度
        // 遍历属性数组，为每个属性添加一个JLabel标签
        // 为每个属性添加一个显示初始值为"0"的标签，通过createValueLabel方法创建
        // 创建一个JPanel对象，并设置其布局为GridLayout，参数(0, 2)表示无限行，每行2列
        effortValuePanel = new JPanel(new GridLayout(0, 2));
        // 设置面板的边框，边框标题为"学习力"
        effortValuePanel.setBorder(new TitledBorder("学习力"));
        effortFields.clear();

        // 返回创建的面板
        String[] attributes = {"体力","攻击", "防御", "特攻", "特防", "速度"};
        for (String attr : attributes) {
            effortValuePanel.add(new JLabel(attr));
            JTextField tf = new JTextField("0", 3);

            // 为每个输入框添加文档监听器
            tf.getDocument().addDocumentListener(new DocumentListener() {
                public void changedUpdate(DocumentEvent e) { updateRemaining(); }
                public void removeUpdate(DocumentEvent e) {
                    if(tf.getText().isEmpty()) updateRemaining();
                }
                public void insertUpdate(DocumentEvent e) { updateRemaining(); }
            });
            effortValuePanel.add(tf);
            effortFields.add(tf); // 保存输入框引用
        }
        // 添加剩余学习力显示
        effortValuePanel.add(new JLabel("剩余学习力："));
        JLabel remainingLabel = new JLabel("510", SwingConstants.LEFT);
        remainingLabel.setFont(new Font("微软雅黑", Font.BOLD, 16));
        effortValuePanel.add(remainingLabel);

        return effortValuePanel;
    }

    // 计算剩余学习力计算
    private void updateRemaining() {
        int total = 0;
        try {
            for (JTextField tf : effortFields) {
                String input = tf.getText().trim();
                int value = input.isEmpty() ? 0 : Integer.parseInt(input);
                total += Math.max(value, 0); // 负数视为0

            }
        } catch (NumberFormatException e) {
            // 处理非法输入
            return;
        }

        int remaining = 510 - total;

        // 更新显示
        Component[] components = effortValuePanel.getComponents();
        if (components.length > 12) { // 最后两个组件是剩余学习力显示
            JLabel remainingLabel = (JLabel) components[13];
            remainingLabel.setText(String.valueOf(remaining));

            // 设置颜色提示
            remainingLabel.setForeground(remaining < 0 ? Color.RED : Color.BLACK);
        }
    }

    //初始化学习力输入框
    private JLabel createValueLabel(String text) {

        JLabel label = new JLabel(text, SwingConstants.CENTER);
        label.setBorder(BorderFactory.createLineBorder(Color.GRAY));
        return label;
    }
}
